#ifndef __COMPONENT_PATHFINDING_H__
#define __COMPONENT_PATHFINDING_H__

#include "Components/Component.hpp"
#include "Engine/MathUtils.hpp"
#include "EasyMachine.hpp"
#include <memory>
#include "Engine/Vector3.hpp"
#include "AStar/PathfindingResult.hpp"

using namespace PocketSurvival::Engine;

namespace PocketSurvival
{
    struct ComponentCreature;
    struct ComponentPilot;
    struct ComponentBody;
    struct ComponentPathfinding;

    struct ComponentPathfinding : public Component
    {
    protected:
        enum class MachineState
        {
            Stopped,
            MovingDirect,
            SearchingForPath,
            MovingWithPath,
            MovingRandomly,
            Stuck
        };

        class StateMachine : public EasyMachine<MachineState>
        {
        protected:
            ComponentPathfinding * m_pathfinding;
        public:
            StateMachine(ComponentPathfinding *pathfinding);

            virtual void enter() override;
            virtual void update(float dt) override;
            virtual void leave() override;
        };

    protected:
        float m_importanceLevel;
        StateMachine *m_stateMachine;

    public:
        ~ComponentPathfinding();

        ComponentCreature *componentCreature;
        ComponentPilot *componentPilot;

        PathfindingResult pathfindingResult;
        bool destinationChanged;
        double nextUpdateTime;
        float pathfindingCongestion;
        int32_t randomMoveCount;
        double lastPathfindingTime;
        
        Vector3 lastPathfindingDestination = FastVector3::Zero;
        Vector3 destination = FastVector3::Zero;
        float range;
        float speed;
        int32_t maxPathfindingPositions;
        bool useRandomMovements;
        bool ignoreHeightDifference;
        bool raycastDestination;
        ComponentBody *doNotAvoidBody = nullptr;
        bool isStuck;

        void setDestination(const Vector3 &theDestination, float theSpeed, float theRange, int32_t theMaxPathfindingPositions, bool theUseRandomMovements, bool theIgnoreHeightDifference, bool theRaycastDestination, ComponentBody *theDoNotAvoidBody);
        void stop();

        virtual void update(float dt) override;
        virtual void load(const nlohmann::json &jsonData) override;
        virtual const std::string &getName() const override;
        static const std::string &GetName();
    };
}

#endif
